home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-08-26 | 53.0 KB | 1,553 lines |
- Newsgroups: comp.sources.misc
- From: Lutz Prechelt <prechelt@i41s14.ira.uka.de>
- Subject: v22i063: crefine - C-Refine preprocessor, Part01/04
- Message-ID: <csm-v22i063=crefine.222259@sparky.imd.sterling.com>
- X-Md4-Signature: ad2ce72e818406e8bba5abec3b00b826
- Date: Mon, 26 Aug 1991 03:23:53 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: Lutz Prechelt <prechelt@i41s14.ira.uka.de>
- Posting-number: Volume 22, Issue 63
- Archive-name: crefine/part01
- Environment: UNIX, MS-DOS, TOS, C, C++, Objective-C
-
- C-Refine is a preprocessor for programs written in C or C++ or a similar
- language. It introduces an additional language construct called 'refinement'
- which allows further decomposition with symbolic names inside functions.
- This makes programs much easier to read and modify and is very comfortable
- for programming.
-
- C-Refine should work with any language that closely resembles C-Syntax and
- with any operating system that supports C-style I/O (stdio.h)
-
- The installed system consists of a single executable file (crefine) and one
- Unix Manualpage (crefine.1). No further data files or libraries
- except the standard C library are needed, so C-Refine is easily portable.
-
- Lutz
-
- Lutz Prechelt (++49/721/608-4317, FAX: ++49/721/697760) | Whenever you
- Institut fuer Programmstrukturen und Datenorganisation | complicate things,
- Universitaet Karlsruhe; D-7500 Karlsruhe 1; Germany | they get
- prechelt@ira.uka.de or prechelt!ira.uka.de@relay.csnet | less simple.
-
- ----------------------------cut here-------------------------------------
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # The tool that generated this appeared in the comp.sources.unix newsgroup;
- # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
- # Contents: README To_Do cr_getln.cr crefine.c
- # Wrapped by kent@sparky on Sun Aug 25 21:56:45 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 1 (of 4)."'
- if test -f 'README' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'README'\"
- else
- echo shar: Extracting \"'README'\" \(3287 characters\)
- sed "s/^X//" >'README' <<'END_OF_FILE'
- X/*
- X Copyright (C) 1987-1991 by Lutz Prechelt, Karlsruhe
- X
- X This program is free software; you can redistribute it and/or modify
- X it under the terms of the GNU General Public License as published by
- X the Free Software Foundation; either version 1, or (at your option)
- X any later version.
- X This program is distributed in the hope that it will be useful,
- X but WITHOUT ANY WARRANTY; without even the implied warranty of
- X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- X GNU General Public License for more details.
- X You should have received a copy of the GNU General Public License
- X along with this program; if not, write to the Free Software
- X Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- X*/
- X
- X>>>>> This is README for C-Refine Version 2.4 <<<<<
- X
- XC-Refine is a preprocessor for programs written in C or C++ or a similar
- Xlanguage. It introduces an additional language construct called 'refinement'
- Xwhich allows further decomposition with symbolic names inside functions.
- XThis makes programs much easier to read and modify and is very comfortable
- Xfor programming.
- X
- XThe system consists of a single executable file (crefine) and one
- XUnix Manualpage (crefine.1). No further data files or libraries
- Xexcept the standard C library are needed.
- X
- X------------------------------------------------------------------------------
- X
- XTo generate C-Refine (which is bootstrapped, i.e. written in C-Refine)
- Xyou must first compile the preprocessed version of the files.
- X
- XThis is done with the command
- X make crefine_from_c
- Xwhich always compiles and links all 4 parts.
- X
- XIf you have a working version of C-Refine you can bootstrap it via
- X make crefine
- X
- XThe makefile also mentions a rule for translating in one step from
- XC-Refine to .o
- X
- X------------------------------------------------------------------------------
- X
- XIf you have gotten C-Refine to work on a machine not mentioned below,
- Xplease send me (prechelt@ira.uka.de) a short note of the form:
- X
- X Subject: got C-Refine working
- X I got C-Refine 2.4 to work without problems on the following machine
- X <name-of-computer> <name-and-version-of-operating-system>
- X
- X(...or describe why C-Refine didn't compile and perhaps send me a minimal
- Xdiff to get it to work.)
- X
- X------------------------------------------------------------------------------
- X
- XEnvironments where C-Refine already works:
- X
- X(CF is the certainty factor with the following meaning:
- X 1: compiles (I have checked that)
- X 2: most probably compiles (but I don't have machine at hand to check again)
- X 3: probably compiles (it once did, but changes may have reversed this)
- X 4: should compile (have done my best from what I know about that system)
- X 5: may compile (a bit doubtful)
- X)
- X
- XCF Machine Operating System (and perhaps Compiler)
- X
- X1 DECstation 3100 Ultrix 4.1
- X3 IBM PC etc. MS-DOS 3.2 (Microsoft C 5.0)
- X3 PCS (type???) (some System V)
- X2 Sun3 SUN-OS 3.5
- X1 Sun3,Sun4 SUN-OS 4.03
- X1 Sun3,Sun4 SUN-OS 4.1
- X1 VAXstation 3250 Ultrix-32 V3.1
- X
- X------------------------------------------------------------------------------
- X
- XThe Makefile will not work with some prehistoric versions of "make".
- XIn this case I strongly suggest that you get a newer make, e.g. GNU-Make.
- END_OF_FILE
- if test 3287 -ne `wc -c <'README'`; then
- echo shar: \"'README'\" unpacked with wrong size!
- fi
- # end of 'README'
- fi
- if test -f 'To_Do' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'To_Do'\"
- else
- echo shar: Extracting \"'To_Do'\" \(475 characters\)
- sed "s/^X//" >'To_Do' <<'END_OF_FILE'
- X Things to do in C-Refine as of 22.08.91
- X==========================
- X
- X1. Lutz Prechelt, 11.06.91
- X Handle #line directives in form (<ws> is whitespace, i.e. Blank or Tab)
- X #[<ws>...][line<ws>...]<linenumber>[<ws>..."<filename>"]
- X so e.g.
- X #line 11 "abc.x"
- X # 15 "abc.c"
- X
- X2. Lutz Prechelt, 11.06.91
- X Handle stdin and stdout as files via "-" syntax
- X
- X3. Lutz Prechelt, 11.06.91
- X Handle multiple input files:
- X Enforce stripping of "r" at end of input file name
- END_OF_FILE
- if test 475 -ne `wc -c <'To_Do'`; then
- echo shar: \"'To_Do'\" unpacked with wrong size!
- fi
- # end of 'To_Do'
- fi
- if test -f 'cr_getln.cr' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'cr_getln.cr'\"
- else
- echo shar: Extracting \"'cr_getln.cr'\" \(14951 characters\)
- sed "s/^X//" >'cr_getln.cr' <<'END_OF_FILE'
- X/*************************************************************************
- XProject : C-Refine Precompiler
- XModule : Line Scanner
- XAuthor : Lutz Prechelt, Karlsruhe
- XDate : 11.06.91 Version 16
- XCompiler: ANSI C
- X**************************************************************************/
- X/*
- X Copyright (C) 1988,89,90,91 by Lutz Prechelt, Karlsruhe
- X
- X This program is free software; you can redistribute it and/or modify
- X it under the terms of the GNU General Public License as published by
- X the Free Software Foundation; either version 1, or (at your option)
- X any later version.
- X This program is distributed in the hope that it will be useful,
- X but WITHOUT ANY WARRANTY; without even the implied warranty of
- X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- X GNU General Public License for more details.
- X You should have received a copy of the GNU General Public License
- X along with this program; if not, write to the Free Software
- X Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- X*/
- X
- X/************************************************************************
- X*********************** C - R e f i n e *********************************
- X*************************************************************************/
- X
- X#include <stdio.h>
- X#include <string.h>
- X#include <ctype.h>
- X
- X#include "cr_decl.h" /* globale Funktionen, Typen und Daten */
- X
- X/******************* lokale Funktionen ************************************/
- X
- Xstatic void push_refinement_name A(());
- Xstatic int normal_scanner A((LINE_INFO*));
- Xstatic int comment_scanner A((LINE_INFO*));
- Xstatic int text_scanner A((LINE_INFO*));
- Xstatic int char_scanner A((LINE_INFO*));
- X
- X/*************************** defines ***************************************/
- X
- X#define push(ch) *(s++) = (char)ch
- X
- X#define leave_sequence "leave" /* e.g. "leave" (no leading blank!) */
- X#define leave_sequence_length 5
- X
- X#define normal_end_of_line 1 /* real end of line */
- X#define continueing_end_of_line 2 /* logical end of line */
- X#define refinementsymbol_found 3
- X#define leave_keyword_found 4
- X
- X/*********************** Lokale Daten ************************************/
- X
- X/***** one line buffer *****/
- Xstatic char *act; /* current position in b */
- X
- X/***** Control *****/
- X#if ansi
- Xstatic int (*scanner) (LINE_INFO*) = normal_scanner;
- X#else
- Xstatic int (*scanner) () = normal_scanner;
- X#endif
- X/***** Status *****/
- Xstatic int level = 0, /* brace-nesting */
- X just_was = normal_end_of_line, /* event memory */
- X event = normal_end_of_line,
- X semicolon_count,
- X lines_in_denoter,
- X old_indent;
- X
- X/*********************** get_line ****************************************/
- X
- Xextern void get_line (fp, l, semicolons)
- X FILE *fp;
- X LINE_INFO *l;
- X int *semicolons; /* is increased only ! */
- X{
- X /* Reads on line from file fp and sets up l accordingly.
- X The preprocessed line is copied to *s and s is increased appropriately.
- X (A null terminator is appended.)
- X The line is a complete line only, if there is no refinement involved
- X with that line:
- X For refinement calls and refinement declaration headers a separate line
- X is generated.
- X At end of file stop_processing is set to true. Problems yield a
- X message and let 'errors' or 'warnings' increase.
- X This function uses the option indicator variables.
- X */
- X charp old_s = s; /* store s to compute length later */
- X bool stop = false;
- X bool three_witches;
- X semicolon_count = 0;
- X `init l;
- X if (just_was == normal_end_of_line) {
- X `read line;
- X `get indent;
- X }
- X else { /* continued line */
- X l->indent = old_indent;
- X l->line_no = line_no;
- X }
- X `handle line;
- X
- X`init l:
- X#if debug
- X printf ("get_line:");
- X#endif
- X l->level = level; /* level is defined as level at start of line! */
- X l->start = s;
- X l->indent = 0;
- X l->type = normal;
- X
- X`read line:
- X l->line_no = ++line_no;
- X act = (char*)fgets (b, b_size, fp); /* get next line*/
- X#if debug
- X printf ("->%s<-", act == NULL ? "(NULL)" : (char*)act);
- X#endif
- X if (act == NULL) { /* check for EOF */
- X stop_processing = true;
- X l->type = empty;
- X if (level > 0)
- X error (Eeof_brace, NULL, line_no);
- X if (scanner == comment_scanner)
- X error (Eeof_comment, NULL, line_no);
- X if (scanner == text_scanner)
- X error (Eeof_string, NULL, line_no);
- X if (scanner == char_scanner)
- X error (Eeof_char, NULL, line_no);
- X return;
- X }
- X
- X`get indent:
- X while (!stop)
- X if (*act == ' ') {
- X l->indent++;
- X act++;
- X }
- X else if (*act == TAB) { /* expand Tabs */
- X l->indent = (l->indent/tabsize + 1) * tabsize;
- X act++;
- X }
- X else
- X stop = true;
- X old_indent = l->indent; /* store for next call */
- X
- X`handle line:
- X three_witches = l->indent == 0 && level > 0 && scanner == normal_scanner;
- X if (three_witches && (int)*act == refinementsymbol)
- X `handle_refinement_declaration;
- X else {
- X `check column 0;
- X if (just_was != refinementsymbol_found &&
- X just_was != leave_keyword_found)
- X event = (*scanner) (l);
- X `handle_event;
- X if (option_small || event == normal_end_of_line)
- X `delete trailing blanks;
- X }
- X l->length = s - old_s;
- X if (l->length == 0)
- X l->type = empty;
- X push (0); /* String Terminator */
- X `perhaps warn for level changes;
- X assert (!(l->type == refdecl && semicolon_count != 0));
- X *semicolons += semicolon_count;
- X
- X`handle_refinement_declaration:
- X act++; /* skip refinementsymbol */
- X push_refinement_name ();
- X if (*act != ':')
- X error (Erefdecl_syntax, act, line_no);
- X else
- X act++;
- X if (level > 1)
- X error (Erefdecl_nested, NULL, line_no);
- X l->type = refdecl;
- X just_was = (*act == '\n' || *act == 0) ? normal_end_of_line :
- X continueing_end_of_line;
- X
- X`check column 0:
- X if (three_witches && !iscntrl (*act) &&
- X just_was != continueing_end_of_line &&
- X *act != '}' && *act != '#' && *act != '*' && *act != '/')
- X warning (Wcol0, act, line_no, 1);
- X
- X`handle_event:
- X if (event == refinementsymbol_found || event == leave_keyword_found)
- X `handle refinementcall or leave;
- X else
- X just_was = normal_end_of_line;
- X
- X`handle refinementcall or leave:
- X if (s - old_s == 0) { /* line empty */
- X push_refinement_name ();
- X l->type = event == leave_keyword_found ? leave : refcall;
- X `skip semicolon and blanks;
- X just_was = (*act == 0 || *act == '\n') ? normal_end_of_line :
- X continueing_end_of_line;
- X }
- X else
- X just_was = event;
- X
- X`skip semicolon and blanks:
- X if (*act == ';') { /* skip semikolon if present */
- X act++;
- X semicolon_count++;
- X if (l->type == refcall)
- X l->type = refcallr; /* note the removed ";" */
- X }
- X while (*(act++) == ' ') /* skip following blanks */
- X ;
- X act--; /* recover char after last blank */
- X
- X`delete trailing blanks:
- X while (*(s-1) == ' ') /* remove trailing blanks */
- X s--;
- X
- X`perhaps warn for level changes:
- X int lev = level;
- X if (lev < 0) { /* Syntax error! (or C-Refine does not work...) */
- X if (option_anyway)
- X error (Emany_braces, NULL, line_no);
- X else
- X fatal_error (Emany_braces, NULL, line_no);
- X }
- X else if (lev > 5 && level > l->level)
- X warning (Wnesting, NULL, line_no, 3);
- X else if (l->indent > 35 && `is refcall && !option_small)
- X warning (Wmuch_indent, NULL, line_no, 3);
- X
- X`is refcall:
- X l->type == refcall || l->type == refcallr
- X}
- X
- X/********************** push_refinement_name *******************************/
- X
- Xstatic void push_refinement_name ()
- X{
- X /* reads input using 'act' and generates output using 's'.
- X reads all following blanks, letters, digits and underscores (that is,
- X stops on other characters) and generates from that a C identifier
- X on the output by suppressing leading and trailing blanks.
- X With option_ibmchars the Umlaute and Accentcharacters from the
- X IBM International Charset are also allowed.
- X */
- X#define is_legal(ch) (isalnum(ch) || (ch) == ' ' || ch == '_' || \
- X (option_ibmchars && \
- X (((ch) >= 128 && (ch) <= 167)) || (ch) == 225))
- X int ch;
- X charp old_s = s, start = s;
- X `suppress leading blanks;
- X `copy legal chars;
- X `suppress trailing blanks;
- X assert (*(s-1) != ' ');
- X assert (*old_s != ' ');
- X assert (s - old_s >= 0);
- X `change inner blanks to underlines;
- X if (s - old_s == 0)
- X error (Erefname_missing, act, line_no);
- X
- X`suppress leading blanks:
- X while (*act == ' ') /* suppress leading blanks */
- X act++;
- X
- X`copy legal chars:
- X do { /* copy legal chars */
- X ch = *(act++);
- X push (ch);
- X }
- X while (is_legal (ch));
- X s--; act--; /* unpush illegal last char */
- X
- X`suppress trailing blanks:
- X while (*(s-1) == ' ' && s > old_s) /* suppress trailing blanks */
- X s--;
- X
- X`change inner blanks to underlines:
- X for (start++; start < s; start++) /* change inner blanks to underlines */
- X if (*start == ' ')
- X *start = '_';
- X#undef is_legal
- X}
- X
- X/*********************** S C A N N I N G *********************************/
- X
- X#define q 39 /* Quote */
- X#define dq 34 /* Double-Quote */
- X
- X/*********************** normal_scanner ***********************************/
- X
- Xstatic int normal_scanner (l)
- X LINE_INFO *l;
- X{
- X /* Changes to reading comments, strings or quoted chars as necessary.
- X Ends only at the end of a line.
- X Tries to identify refinement calls and refinement declarations;
- X in these cases the lines are reduced to only the refinement name.
- X */
- X register int ch;
- X for (;;) {
- X ch = *(act++);
- X switch (ch) {
- X case '\n':
- X case 0 : return (normal_end_of_line);
- X case '/' : if (*act == '*') /* start of comment ? */
- X `handle normal comment;
- X else if (*act == '/' && option_cplusplus)
- X `handle doubleslash style comment;
- X else /* No --> normal */
- X push (ch);
- X break;
- X case dq :
- X `handle text denoter;
- X case q :
- X `handle char denoter;
- X case ';' : semicolon_count++;
- X push (';');
- X break;
- X case '{' : level++;
- X push (ch);
- X break;
- X case '}' : level--;
- X push (ch);
- X break;
- X default :
- X if (ch == refinementsymbol)
- X `check for leave or refinement call;
- X else
- X push (ch);
- X }
- X }
- X
- X`handle normal comment:
- X if (!option_small) {
- X push (ch); push ('*');
- X }
- X act++;
- X scanner = comment_scanner;
- X return ((*scanner) (l));
- X
- X`handle doubleslash style comment:
- X if (option_small)
- X return (normal_end_of_line); /* just pgnore rest of line */
- X push (ch); push (ch); /* put // */
- X act++;
- X while (*act != '\n' && *act != 0) /* put rest of line */
- X push (*(act++));
- X return (normal_end_of_line);
- X
- X`handle text denoter:
- X push (ch);
- X scanner = text_scanner;
- X lines_in_denoter = 0;
- X return ((*scanner) (l));
- X
- X`handle char denoter:
- X push (ch);
- X scanner = char_scanner;
- X lines_in_denoter = 0;
- X return ((*scanner) (l));
- X
- X`check for leave or refinement call :
- X /* Precondition: Refinement symbol found, 'act' is right behind it.
- X if a 'leave' surrounded by blanks is found in front of the
- X refinement symbol, it and its blanks are stripped and
- X leave_keyword_found is returned.
- X Otherwise refinementsymbol_found gemeldet is returned
- X */
- X charp old_s = s--;
- X while (*s == ' ')
- X s--;
- X s++;
- X if (!memcmp (s - leave_sequence_length, leave_sequence,
- X leave_sequence_length)) {
- X s -= leave_sequence_length; /* Remove leave_sequence from Output */
- X return (leave_keyword_found);
- X }
- X else {
- X s = old_s;
- X return (refinementsymbol_found);
- X }
- X}
- X
- X/********************* comment_scanner *************************************/
- X
- Xstatic int comment_scanner (l)
- X LINE_INFO *l;
- X{
- X /* Precondition: position is right behind a start of a comment
- X (which is already copied if not option_small is true)
- X Postcondition: position is right after a comment end.
- X */
- X register int ch;
- X for (;;) {
- X ch = *(act++);
- X switch (ch) {
- X case '\n':
- X case 0 : return (normal_end_of_line);
- X case '*' : if (*act == '/') /* end of comment : */
- X `handle comment end;
- X /* no break ! */
- X default : if (!option_small)
- X push (ch);
- X }
- X }
- X
- X`handle comment end:
- X if (!option_small) {
- X push (ch); push ('/');
- X }
- X act++;
- X scanner = normal_scanner; /* change to normal scanner */
- X return ((*scanner) (l)); /* and continue scanning */
- X
- X}
- X
- X/********************* text_scanner *************************************/
- X
- Xstatic int text_scanner (l)
- X LINE_INFO *l;
- X{
- X /* Precondition: position is right behind the (already copied)
- X double quote that starts a string denoter
- X (string literal)
- X Postcondition:position is right behind the closing double
- X quote of a string denoter
- X */
- X register int ch;
- X lines_in_denoter++;
- X for (;;) {
- X ch = *(act++);
- X switch (ch) {
- X case '\n':
- X case 0 : return (normal_end_of_line); /* allowed ??? */
- X case dq : `end of stringdenoter;
- X case '\\': push (ch);
- X if (*act == dq || *act == '\\') {
- X push (*act);
- X act++;
- X }
- X break;
- X default : push (ch);
- X }
- X }
- X
- X`end of stringdenoter:
- X push (ch);
- X if (lines_in_denoter > 1)
- X warning (Wlong_string, act-1, line_no,
- X lines_in_denoter > 5 ? 1 : 2);
- X scanner = normal_scanner;
- X return ((*scanner) (l));
- X
- X}
- X
- X/********************* char_scanner *************************************/
- X
- Xstatic int char_scanner (l)
- X LINE_INFO *l;
- X{
- X /* Is analogous to text scanner, but uses single quote instead of double
- X quote.
- X */
- X int ch;
- X lines_in_denoter++;
- X for (;;) {
- X ch = *(act++);
- X switch (ch) {
- X case '\n':
- X case 0 : return (normal_end_of_line); /* allowed ??? */
- X case q : `end of chardenoter;
- X case '\\': push (ch);
- X if (*act == q || *act == '\\') {
- X push (*act);
- X act++;
- X }
- X break;
- X default : push (ch);
- X }
- X }
- X
- X`end of chardenoter:
- X push (ch);
- X if (lines_in_denoter > 1)
- X warning (Wlong_char, act-1, line_no,
- X lines_in_denoter > 5 ? 1 : 2);
- X scanner = normal_scanner;
- X return ((*scanner) (l));
- X
- X}
- X
- END_OF_FILE
- if test 14951 -ne `wc -c <'cr_getln.cr'`; then
- echo shar: \"'cr_getln.cr'\" unpacked with wrong size!
- fi
- # end of 'cr_getln.cr'
- fi
- if test -f 'crefine.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'crefine.c'\"
- else
- echo shar: Extracting \"'crefine.c'\" \(30121 characters\)
- sed "s/^X//" >'crefine.c' <<'END_OF_FILE'
- X
- X/*************************************************************************
- XProject : C-Refine Precompiler
- XModule : main module
- XAuthor : Lutz Prechelt, Karlsruhe
- XDate : 10.06.91 Version 16
- XCompiler: ANSI C, C-Refine 2.3 (bootstrapped)
- X**************************************************************************/
- X/*
- X Copyright (C) 1988,89,90,91 by Lutz Prechelt, Karlsruhe
- X
- X This program is free software; you can redistribute it and/or modify
- X it under the terms of the GNU General Public License as published by
- X the Free Software Foundation; either version 1, or (at your option)
- X any later version.
- X This program is distributed in the hope that it will be useful,
- X but WITHOUT ANY WARRANTY; without even the implied warranty of
- X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- X GNU General Public License for more details.
- X You should have received a copy of the GNU General Public License
- X along with this program; if not, write to the Free Software
- X Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- X*/
- X
- X/************************************************************************
- X*********************** C - R e f i n e *********************************
- X*************************************************************************/
- X
- X#if 0
- XREMARK:
- X This program was originally written using german identifiers and
- X comments. I worked through it to change this (at least in most parts)
- X but please do not flame me if there are relicts from this state.
- X I did not find a sensible replacement for the german word 'Klammer' that
- X may stand for any of the characters ( ) [ ] { } so sometimes I still
- X use the german one.
- X
- XVariants:
- X#define deutsch fuer deutsche Meldungen statt englische
- X#define ms_dos for MS-DOS Operating System (Compiler Microsoft C 5.0)
- X#define unix for Unix
- X#define vms for VMS
- X#define ansi for ANSI-C Compiler
- X
- XFor version changes see refinement startup message and file cr_texts.h
- X
- X============================== History: ====================================
- X
- X
- XVersion 1.0 (Alpha) (0, 1)
- X
- X1987
- X procedural refinements only
- X not comfortable, few error messages
- X
- X
- XVersion 2.0 (Alpha) (2, 3)
- X
- XFeb. 88
- X value-returning refinements,
- X improved error handling,
- X Options comment, feedback, list, numbering, refinementsymbol, small
- X
- X
- XVersion 2.1 (Beta) (4, 5)
- X
- X09.04.88 ( --> Martin, Ihno, Volker, Beat)
- X improved error handling
- X triple error messages (german, english, german nonsense),
- X Context description in error messages,
- X Options anyway, feedback, ibm chars, message type, tabsize, warning level
- X Expires 31.07.88
- X
- X
- XVersion 2.2 (6, 7, 8)
- X
- X08.07.88 ( --> Martin)
- X corr: Changes blanks in namen to underscrores again (like in Version 1.0)
- X (otherwise error in goto occur)
- X corr: Removed semicolon after value-returning refinements kept
- X (via introduction of refcallr)
- X improved error handling: Warning for "often used" only for
- X "big" refinements.
- X03.08.88
- X corr: When inserting file names in "#line"-commands, backslashes
- X are doubled (backslash is Escape symbol in C string denoters)
- X13.09.88
- X corr: empty refinements will not give syntax errors anymore.
- X
- X
- XVersion 2.3 (9, 10, 11, 12, 13)
- X
- X29.09.88 ( --> Martin, Ihno)
- X corr: refinements with just 1 semicolon are enclosed in braces also
- X (to avoid "else"-conflict)
- X C++ Mode (i.e. // Kommentare) as option p
- X17.03.89
- X "std.h" introduced, #ifdefs for environment switches introduced.
- X Look-through, further "refinementized", several small corrections
- X ported to SUN-OS (Berkeley-Unix)
- X Size restrictions released (500 -> 800 lines, 50 -> 100 Refinements)
- X18.03.89
- X dito, expires 31.07.89
- X11.09.89
- X ported to PCS maschine under Munix 5.3 (System V)
- X further #ifdefs for deutsch, expire
- X The switches are given in the Makefile
- X11.09.89
- X dito, expires 31.10.89
- X
- X
- XVersion 2.4 (14, 15, 16)
- X
- X27.08.90 ( --> Uni)
- X Line numbering switchable in 4 levels.
- X Quiet-Option
- X Buffersizes selectable via option.
- X New name handling for input/output files
- X
- X23.01.91 ( --> Uni, Usenet announcement, iraun1)
- X Names and Comments changed to english (was german before)
- X error in level switching of line numbering fixed.
- X
- X10.06.91 ()
- X History translated to english
- X some small corrections
- X corr: REF_INFO storage has to be 0-initialized,
- X so use calloc instead of malloc
- X Eliminated duplication of function declarations for ansi and non-ansi
- X by introduction of the A(a) macro in std.h
- X
- X=============================================================================
- X#endif
- X
- X#include <stdio.h>
- X#include <string.h>
- X#include <malloc.h>
- X#include <time.h>
- X
- X#define DATA_HERE /* Here the data declarations are NOT extern */
- X#include "cr_decl.h" /* global Functions, Types and Data */
- X#include "getargs.h"
- X
- X
- X/******************* lokal Functions ************************************/
- X
- Xextern int main A((int argc, charp *argv));
- Xextern int crefine A((int argc, charp *argv));
- Xstatic void process_c_refine A((FILE *in, FILE *out));
- Xstatic void process_line A((FILE *out, int semicolons));
- Xstatic void insert_refinements A((FILE *out));
- Xstatic void insert_refinement A((FILE *out, LINE_INFO *l, int startindent,
- X int recursive_level));
- Xstatic void line_cmd A((FILE* out, int nr, int indent, int min_level));
- Xstatic void put_indent A((FILE *out, int how_much));
- Xstatic void put_line A((FILE *out, LINE_INFO *line, int additional_indent,
- X int min_linenumbering_level));
- Xstatic int refinement_nr A((char *refinementname));
- Xstatic void allocate A((charp *buffer, unsigned *size, unsigned minsize));
- Xstatic void copy_with_doubled_backslashes A((char *string, char *copy));
- Xstatic void do_expire A((int day, int month, int year_in_century));
- Xstatic void reset_l_r_s A((void));
- X
- X/*********************** Lokal Data ************************************/
- X
- X/***** line info, refinement info *****/
- Xstatic LINES l; /* line info */
- Xstatic int l_pos;
- X
- Xstatic REFS r; /* refinement info */
- Xstatic int r_pos;
- X
- X/***** Status *****/
- Xstatic int old_level, /* level at line before */
- X commanded_line_no; /* line_no according to last line_cmd */
- X
- X/***** Sonstiges *****/
- Xstatic char blanks[] = /* indents are made from this. */
- X " ";
- X/* "blanks" is taken as 72 Blanks long (see put_indent) */
- X
- Xstatic option_msg;
- X
- X#define refdecl_line(i) /* line no of refinement head of r[i] */\
- X (l [r[i].firstentry].line_no)
- X
- X/******************************** crefine *********************************/
- X
- Xextern int main (argc, argv) /* MAIN */
- X int argc;
- X charp argv[];
- X{
- X return (crefine (argc, argv));
- X}
- X
- Xstatic ARG argtab[] = {
- X#if deutsch
- X {'a', BOOLEAN, &option_anyway,
- X "alle: Ausgabedatei trotz Fehlern nicht loeschen" },
- X {'c', BOOLEAN, &option_comment, "Refinementnamen-Kommentare in Ausgabe" },
- X {'e', BOOLEAN, &option_indent, "#line Kommandos einruecken" },
- X {'f', BOOLEAN, &option_feedback, "Fortschrittsanzeige (Zeilennummern)" },
- X#if ms_dos
- X {'I', BOOLEAN, &option_ibmchars,
- X "erlaube IBM internationale Zeichen fuer Namen" },
- X#endif
- X {'k', BOOLEAN, &option_comment, "Refinementnamen-Kommentare in Ausgabe" },
- X {'l', BOOLEAN, &option_list, "liste alle Refinementnamen" },
- X {'m', CHARACTER, &option_msg,
- X "Meldungen in: d=deutsch, e=english, sonst humorig" },
- X {'n', INTEGER, &numbering_level,
- X "Stufe der Numerierung mit #line Kommandos" },
- X {'p', BOOLEAN, &option_cplusplus,"C++ Modus" },
- X {'q', BOOLEAN, &option_cplusplus,"keine Startmeldung ausgeben" },
- X {'r', CHARACTER, &refinementsymbol, "Refinementsymbol (als Zeichen)" },
- X {'R', INTEGER, &refinementsymbol, "Refinementsymbol (als Zahl)" },
- X {'s', BOOLEAN, &option_small, "strippen: Kompaktifizierte Ausgabe" },
- X {'w', INTEGER, &warning_level, "Warnstufe (0 - 3)" }
- X {'F', INTEGER, &maxerrors, "Max. Anzahl Fehler" },
- X {'L', INTEGER, &b_size, "Max. Zeilenlaenge" },
- X {'N', INTEGER, &maxref, "Max. Refinements je Funktion" },
- X {'P', INTEGER, &s_size, "Codepuffer in Bytes" },
- X {'T', INTEGER, &tabsize, "Tabulatorgroesse" },
- X {'W', INTEGER, &maxwarnings, "Max. Anzahl Warnungen" },
- X {'Z', INTEGER, &maxline, "Max. Zeilen je Funktion" },
- X#else
- X {'a', BOOLEAN, &option_anyway, "anyway: don't delete output on errors" },
- X {'c', BOOLEAN, &option_comment, "comment refinement names in output" },
- X {'f', BOOLEAN, &option_feedback, "feedback that you work" },
- X {'i', BOOLEAN, &option_indent, "indent the #line commands" },
- X#if ms_dos
- X {'I', BOOLEAN, &option_ibmchars,
- X "enable IBM International Charset for names" },
- X#endif
- X {'l', BOOLEAN, &option_list, "list all refinement names" },
- X {'m', CHARACTER, &option_msg,
- X "Messages in: g=german, e=english, else sense of humor ?" },
- X {'n', INTEGER, &numbering_level,
- X "level of numbering with #line commands" },
- X {'p', BOOLEAN, &option_cplusplus,"C++ mode" },
- X {'q', BOOLEAN, &option_quiet, "quiet mode (no startup message)" },
- X {'r', CHARACTER, &refinementsymbol, "refinementsymbol (character form)" },
- X {'R', INTEGER, &refinementsymbol, "refinementsymbol (decimal form)" },
- X {'s', BOOLEAN, &option_small, "small compactified output" },
- X {'w', INTEGER, &warning_level, "warning level (0 - 3)" },
- X {'B', INTEGER, (int*)&s_size, "code buffer in bytes" },
- X {'E', INTEGER, &maxerrors, "max errors" },
- X {'L', INTEGER, (int*)&maxline, "max lines per function" },
- X {'N', INTEGER, (int*)&maxref, "max refinements per function" },
- X {'T', INTEGER, &tabsize, "tab size" },
- X {'W', INTEGER, &maxwarnings, "max warnings" },
- X#endif
- X};
- X
- X
- Xextern int crefine (argc, argv) /* C-REFINE */
- X int argc;
- X charp argv[];
- X{
- X /* Analyses options and opens files.
- X Then calls process_c_refine and closes files again.
- X Returns the number of errors that have been found
- X */
- X bool two_filenames_given;
- X int wrong_options;
- X FILE *in, *out;
- X { /* analysis_of_options (Level 1) */
- X option_anyway = option_feedback = option_indent = option_comment
- X = option_list = option_ibmchars = option_cplusplus
- X = false;
- X option_small = true;
- X numbering_level = 3;
- X#if deutsch
- X option_msg = 'd';
- X msg_type = 0; /* deutsche Meldungen als Standard */
- X#else
- X option_msg = 'e';
- X msg_type = 1; /* english warnings and errors as default */
- X#endif
- X refinementsymbol = std_refinementsymbol;
- X tabsize = 1;
- X warning_level = 3;
- X maxline = STD_MAXLINE;
- X maxref = STD_MAXREF;
- X b_size = STD_MAXLINELENGTH;
- X s_size = STD_S_SIZE;
- X maxerrors = STD_MAXERRORS;
- X maxwarnings = STD_MAXWARNINGS;
- X wrong_options = getargs (&argc, argv, argtab, ARGTABSIZE (argtab));
- X if (option_small) {
- X tabsize = 1;
- X }
- X if (option_msg == 'd' || option_msg == 'D' ||
- X option_msg == 'g' || option_msg == 'G')
- X msg_type = 0;
- X else if (option_msg == 'e' || option_msg == 'E')
- X msg_type = 1;
- X else
- X msg_type = 2;
- X two_filenames_given = argc == 3;
- X }
- X if (wrong_options || argc>>1 != 1) {
- X print_usage (argv[0], usagestring[msg_type],
- X argtab, ARGTABSIZE (argtab));
- X { /* startup_message (Level 1) */
- X fprintf (stderr,
- X "C-Refine Precompiler %s\n", versionstring[msg_type]);
- X fprintf (stderr,
- X "Copyright (C) 1988,89,90,91 Lutz Prechelt, Karlsruhe\n");
- X }
- X exit (100);
- X }
- X if (!option_quiet)
- X { /* startup_message (Level 1) */
- X fprintf (stderr,
- X "C-Refine Precompiler %s\n", versionstring[msg_type]);
- X fprintf (stderr,
- X "Copyright (C) 1988,89,90,91 Lutz Prechelt, Karlsruhe\n");
- X }
- X { /* open_files_and_complain_if_necessary (Level 1) */
- X strcpy (name_in, argv[1]); /* get */
- X#if ms_dos
- X in = fopen (name_in, "rt"); /* read, translated mode */
- X#else
- X in = fopen (name_in, "r"); /* read */
- X#endif
- X if (in == NULL || ferror (in)) {
- X fprintf (stderr, Eopen[msg_type], name_in);
- X exit (100);
- X }
- X copy_with_doubled_backslashes (name_in, modified_name_in);
- X if (two_filenames_given) { /* if second name given */
- X strcpy (name_out, argv[2]); /* take it as it is */
- X }
- X else { /* else */
- X strcpy (name_out, argv[1]); /* take first name */
- X if (name_out[strlen(name_out)-1] == 'r')
- X name_out[strlen(name_out)-1] = 0; /* remove 'r' from end */
- X else
- X strcat (name_out, "RRR"); /* or append 'RRR' */
- X }
- X#if ms_dos
- X out = fopen (name_out, "wt"); /* write, translated mode */
- X#else
- X out = fopen (name_out, "w"); /* write */
- X#endif
- X if (out == NULL || ferror (out)) {
- X fprintf (stderr, Eopen[msg_type], name_out);
- X exit (100);
- X }
- X }
- X { /* reserve_memory_and_complain_if_necessary (Level 1) */
- X b = malloc (b_size);
- X r = (REFS)calloc ((maxref+1), sizeof (REF_INFO));
- X l = (LINES)malloc ((maxline+1) * sizeof (LINE_INFO));
- X s_root = malloc (s_size);
- X if (!(b && s_root && r && l)) {
- X fprintf (stderr, Ememory[msg_type]);
- X exit (100);
- X }
- X }
- X /* here we go: */
- X rewind (in); /* Begin at the beginning, then proceed until you come */
- X /* to the end, there stop. (from: Alice in Wonderland) */
- X process_c_refine (in, out);
- X fclose (in);
- X fclose (out); /* Schliessen vor unlink noetig ! */
- X if (errors && !option_anyway) /* don't produce errorneous outputfiles */
- X unlink (name_out); /* delete file */
- X if (errors || warnings)
- X#if deutsch
- X fprintf (stderr, "%d Fehler%s %d Warnung%s Ausgabedatei %s\n",
- X errors, errors != 1 ? "" : "",
- X warnings, warnings != 1 ? "en" : "",
- X errors && !option_anyway ?
- X "geloescht" : (errors ? "dennoch erhalten"
- X : "ist fragwuerdig"));
- X#else
- X fprintf (stderr, "%d error%s %d warning%s Output %s\n",
- X errors, errors != 1 ? "s" : "",
- X warnings, warnings != 1 ? "s" : "",
- X errors && !option_anyway ?
- X "deleted" : (errors ? "kept anyway" : "is doubtful"));
- X#endif
- X return (errors);
- X}
- X
- X/************************ process_c_refine *********************************/
- X
- Xstatic void process_c_refine (in, out)
- X FILE *in, *out;
- X{
- X /* Reads the file 'in' to the end line by line via 'get_line' and
- X generates the C source code by inserting the refinement bodies for
- X the calls.
- X Generates error messages for undeclares refinements and warnings for
- X unused or often used ones.
- X Uses the variables stop_processing, errors, warnings,
- X s, l, r and the option indicators.
- X */
- X commanded_line_no = line_no = 0;
- X reset_l_r_s ();
- X if (numbering_level > 0)
- X /* we get a linefeed anyway! */
- X fprintf (out, "#line 1 \"%s\"", modified_name_in);
- X while (!stop_processing)
- X { /* handle_next_line (Level 1) */
- X int semicolons = 0;
- X if (option_feedback && line_no % FEEDBACK_INTERVAL == 0)
- X cout (line_no);
- X if (ferror (in))
- X fatal_error (Ereadinput, l[l_pos-1].start, line_no);
- X if (ferror (out))
- X fatal_error (Ewriteoutput, NULL, line_no);
- X get_line (in, l+l_pos, &semicolons);
- X process_line (out, semicolons);
- X }
- X if (option_feedback)
- X cout (line_no);
- X free (s_root);
- X}
- X
- X/************************** process_line ************************************/
- X
- Xstatic void process_line (out, semicolons)
- X FILE *out;
- X int semicolons;
- X{
- X /* Works on the lines up to the current line l[l_pos] in the way that
- X it decides whether a function has ended and thus the insertion of
- X refinements has to be started.
- X On level 0 all lines are copied from in to out immediately.
- X After a state change from level 0 to level 1 all lines (along with
- X a lineinfo) are kept until the next transition to level 0 and the
- X refinement info is being built.
- X If necessary, error messages for overflow or refinement errors and
- X warnings for not or multiply used refinements are generated.
- X */
- X if (r_pos > 0)
- X r[r_pos - 1].semicolons += semicolons;
- X if (old_level == 0)
- X { /* we_came_from_level_0 (Level 1) */
- X assert (l_pos == 0); /* nothing can be stored from level 0 */
- X if (l[0].level == 0 || stop_processing)
- X { /* remains_on_level_0_so_just_copy_it (Level 2) */
- X if (l[0].type != normal && l[0].type != empty)
- X error (Elevel0_ref, l[0].start, line_no);
- X put_line (out, &l[0], 0, 1);
- X reset_l_r_s ();
- X }
- X else
- X { /* function_has_begun (Level 2) */
- X error_in_this_function = false;
- X old_level = l[0].level; /* neuen Level merken */
- X if (l[0].type == refdecl && r_pos < maxref) { /* empty function */
- X r[r_pos].name = l[0].start;
- X r[r_pos].firstentry = 0;
- X r[r_pos].active = false;
- X r[r_pos++].semicolons = 0;
- X warning (Wempty_function, NULL, line_no - 1, 3);
- X }
- X l_pos++; /* store line */
- X }
- X }
- X else
- X { /* we_were_inside_a_function_or_so (Level 1) */
- X if (l[l_pos].level == 0 || stop_processing)
- X { /* but_now_we_are_outside (Level 2) */
- X insert_refinements (out);
- X put_line (out, &l[l_pos-1], 0, 1); /* last line (Blockklammer) */
- X put_line (out, &l[l_pos], 0, 1); /* the level 0 line */
- X error_in_this_function = false;
- X reset_l_r_s ();
- X }
- X else
- X { /* and_still_keep_being_in (Level 2) */
- X if (l[l_pos].type == refdecl && r_pos < maxref) {
- X r[r_pos].name = l[l_pos].start; /* enter Refinement */
- X r[r_pos].active = false;
- X r[r_pos].firstentry = l_pos;
- X r[r_pos++].semicolons = 0;
- X }
- X old_level = l[l_pos].level;/* store new level */
- X l_pos++; /* store line */
- X if (l_pos >= maxline)
- X fatal_error (Elines_in_func, l[l_pos].start, line_no);
- X if (s - s_root >= s_size - 150) /* Reserve too small */
- X fatal_error (Ebytes_in_func, l[l_pos].start, line_no);
- X }
- X }
- X}
- X
- X/************************ insert_refinements ******************************/
- X
- Xstatic void insert_refinements (out)
- X FILE *out;
- X{
- X /* Replaces the refinement calls with the bodies, after the whole function
- X has been read in.
- X In the output #line statements are generated, except if option
- X numbering_level is zero.
- X Comments and indentations are thrown away if option_small is true.
- X Comments stating the refinement names are inserted in the output if
- X option_comment is true.
- X */
- X int i, end;
- X bool extern_stop = stop_processing; /* Protect last function against */
- X stop_processing = false; /* local use of this variable */
- X r[r_pos].firstentry = l_pos-1; /* line of Blockklammer */
- X r[r_pos].name = NULL;
- X { /* generate_refinement_list_if_necessary (Level 1) */
- X if (option_list && r_pos > 0) {
- X fputc ('\n', stdout);
- X for (i = 0; i < r_pos; i++)
- X fprintf (stdout, "(%d) %s\n", refdecl_line (i), r[i].name);
- X }
- X }
- X { /* find_last_line_to_insert (Level 1) */
- X end = r[0].firstentry - 1;
- X while (l[end].type == empty) /* suppress trailing empty lines */
- X end--;
- X }
- X for (i = 0; i <= end; i++) { /* lines up to first ref. declaration */
- X switch (l[i].type) {
- X case refcall :
- X case refcallr :
- X { /* insert_refinement (Level 1) */
- X insert_refinement (out, l+i, l[i].indent, 1);
- X if (stop_processing)
- X return;
- X }
- X break;
- X case leave :
- X { /* whatshallthatbe (Level 1) */
- X assert (false);
- X }
- X break;
- X case normal :
- X { /* insert_normal_line (Level 1) */
- X put_line (out, &l[i], 0, 1);
- X }
- X break;
- X case empty :
- X putc ('\n', out);
- X commanded_line_no++;
- X break;
- X case refdecl :
- X default :
- X assert (false);
- X }
- X }
- X { /* maybe_give_sermon_on_refinements (Level 1) */
- X for (i = 0; i < r_pos; i++)
- X if (r[i].semicolons > 50)
- X warning (Wlong_ref, l[r[i].firstentry].start,
- X refdecl_line (i), 3);
- X else if (r[i].calls > 5 && r[i].semicolons > 2)
- X warning (Wref_often_used, l[r[i].firstentry].start,
- X refdecl_line (i), 3);
- X else if (r[i].calls == 0)
- X warning (Wref_unused, l[r[i].firstentry].start,
- X refdecl_line (i), 1);
- X }
- X stop_processing = stop_processing || extern_stop; /* Merging-Restore */
- X}
- X
- X/************************* insert_refinement ******************************/
- X
- Xstatic void insert_refinement (out, z, startindent, recursive_level)
- X FILE *out;
- X LINE_INFO *z;
- X int startindent, recursive_level;
- X{
- X /* Looks for the refinement to insert by its name, computes the range
- X of lines to work on and does then do the same as insert_refinements
- X does.
- X If necessary the refinement name is given as a comment before the
- X body is inserted.
- X The refinement body is enclosed in delimiters:
- X if ref.semicolons == 0 in parentheses (on first and last line)
- X if ref.semicolons >= 1 in curly braces (on separate lines)
- X The refinement calls are counted and maybe messages generated.
- X In case of leave-statements the refinement that shall be leave'd is
- X marked, so a label can be generated.
- X Errors:
- X 1. Refinement is not declared
- X 2. recursive call to refinement
- X 3. leave is impossible because the refinement is not
- X present in static call hierarchy
- X */
- X int i;
- X int nr, ref_startindent, end;
- X assert (startindent > 0);
- X nr = refinement_nr ((
- X z->start)
- X ); /* search for refinement */
- X if (nr == -1) {
- X error (Eref_not_decl, (
- X z->start)
- X , z->line_no);
- X return;
- X }
- X else if (r[nr].active)
- X { /* complain_for_recursive_refinement_call (Level 1) */
- X error (Erecursive_ref, (
- X z->start)
- X , z->line_no);
- X stop_processing = true;
- X return;
- X }
- X else {
- X r[nr].calls++; /* register the call */
- X r[nr].active = true;
- X r[nr].leave_it = false;
- X }
- X end = r[nr+1].firstentry - 1;
- X while (l[end].type == empty) /* suppress trailing empty lines */
- X end--;
- X i = r[nr].firstentry + 1;
- X if (i > end)
- X warning (Wref_empty, l[r[nr].firstentry].start, refdecl_line (nr), 2);
- X else
- X { /* insert_the_refinement (Level 1) */
- X /* for an empty refinement, this is not called at all! */
- X { /* write_indentation_and_opening_klammer (Level 2) */
- X int sc = r[nr].semicolons;
- X if (sc > 0)
- X put_indent (out, startindent);
- X putc (sc > 0 ? '{' : '(', out); /* Klammer auf */
- X if (option_comment && sc > 0)
- X fprintf (out, Tlistline[msg_type], (
- X z->start)
- X , recursive_level);
- X }
- X ref_startindent = l[i].indent;
- X for ( ; i <= end; i++) {
- X switch (l[i].type) {
- X case refcall :
- X case refcallr :
- X { /* insert_refinement (Level 2) */
- X insert_refinement (out, l+i,
- X startindent + l[i].indent
- X - ref_startindent,
- X recursive_level+1);
- X }
- X break;
- X case leave :
- X { /* insert_goto_statement (Level 2) */
- X int leave_nr = refinement_nr (l[i].start);
- X if (leave_nr == -1)
- X error (Eunknown_leave, l[i].start, l[i].line_no);
- X else if (!r[leave_nr].active)
- X error (Eleave_unpresent, l[i].start, l[i].line_no);
- X else {
- X r[leave_nr].leave_it = true;
- X put_indent (out, startindent);
- X fprintf (out, "goto %s_%d;",
- X l[i].start, r[leave_nr].calls);
- X }
- X }
- X break;
- X case normal :
- X { /* insert_normal_line (Level 2) */
- X put_line (out, &l[i], startindent - ref_startindent, (
- X r[nr].semicolons == 0 ? 3 : 2)
- X );
- X }
- X break;
- X case empty :
- X putc ('\n', out);
- X commanded_line_no++;
- X break;
- X case refdecl :
- X default :
- X assert (false);
- X }
- X }
- X if (r[nr].leave_it)
- X { /* generate_label (Level 2) */
- X fprintf (out, "\n%s_%d: ;", (
- X z->start)
- X , r[nr].calls);
- X commanded_line_no++;
- X }
- X { /* write_closing_klammer (Level 2) */
- X int sc = r[nr].semicolons;
- X if (sc > 0) {
- X put_indent (out, startindent);
- X putc ('}', out);
- X }
- X else {
- X putc (')', out);
- X if (z->type == refcallr) /* semicolon has been removed illegaly */
- X putc (';', out);
- X }
- X }
- X }
- X r[nr].active = false;
- X return;
- X}
- X
- X/************************* line_cmd **************************************/
- X
- Xstatic void line_cmd (out, nr, indent, min_level)
- X FILE *out;
- X int nr;
- X int indent;
- X int min_level;
- X{
- X /* Writes a "preprocessor #line directive" including file name if
- X requested.
- X Is suppressed, if min_level is less than numbering_level.
- X Using numbering_level, option_indent, commanded_line_no and name_in
- X */
- X if (numbering_level >= min_level) {
- X if (option_indent)
- X put_indent (out, indent);
- X else
- X putc ('\n', out);
- X fprintf (out, "#line %d \"%s\"", nr, modified_name_in);
- X commanded_line_no = nr-1; /* #line 3 means: next comes line 3 ! */
- X }
- X}
- X
- X/********************** put_indent **************************************/
- X
- Xstatic void put_indent (out, how_far)
- X FILE *out;
- X int how_far;
- X{
- X putc ('\n', out); /* begin newline */
- X commanded_line_no++;
- X if (!option_small)
- X fwrite (blanks, how_far > 72 ? 72 : (how_far < 0 ? 0 : how_far),
- X 1, out);
- X}
- X
- X/*************************** put_line ***********************************/
- X
- Xstatic void put_line (out, line, additional_indent, min_level)
- X FILE *out;
- X LINE_INFO *line; /* pointer for efficiency (is big object) */
- X int additional_indent;
- X int min_level;
- X{
- X /* Writes the line 'line' to 'out' with the appropriate indentation
- X (which is the line's indentation plus additional_indent).
- X If the current line numbering is not right a line_cmd is made before.
- X */
- X if (line->line_no != commanded_line_no + 1)
- X line_cmd (out, line->line_no, line->indent + additional_indent,
- X min_level);
- X if (line->type == empty) { /* for empty lines: nothing */
- X putc ('\n', out);
- X commanded_line_no++;
- X return;
- X }
- X else if (option_small || (!option_indent && *line->start == '#')) {
- X putc ('\n', out);
- X commanded_line_no++;
- X }
- X else
- X put_indent (out,
- X line->indent + additional_indent); /* starts new line */
- X assert (line->start != NULL);
- X fputs (line->start, out);
- X#if debug
- X fprintf (stdout, "put:\"%s\"\n", line->start);
- X#endif
- X}
- X
- X/********************** refinement_nr ************************************/
- X
- Xstatic int refinement_nr (name)
- X char *name;
- X{
- X /* computes the number of a refinement from its name 'name'.
- X Uses r from 0 to r_pos. Returns the number or -1 if undeclared.
- X If the refinement is declared more than once an error message is
- X generated.
- X */
- X int i, match = -1, matches = 0;
- X assert (name != NULL);
- X for (i = 0; i < r_pos; i++)
- X if (!strcmp (name, r[i].name)) {
- X match = i;
- X matches++;
- X }
- X if (matches > 1)
- X error (Eref_multi_decl, r[match].name, refdecl_line (match));
- X return (match);
- X}
- X
- X/********************* Auxiliary functions ******************************/
- X
- Xstatic void copy_with_doubled_backslashes (string, copy)
- X char *string, *copy;
- X{
- X /* copies the string string to the location copy. All backslash
- X characters (code 92) in string are copied twice, so for example
- X "back\slas\\h" is copied to "back\\slas\\\\h".
- X The purpose of this is to make the copy usable as a C string denoter,
- X in which the backslash is interpreted as an escape symbol.
- X No checks are made, thus there must be enough memory allocated
- X to make the copy.
- X */
- X assert (string != NULL);
- X assert (copy != NULL);
- X while (*string != 0) {
- X *copy = *string;
- X string++;
- X if (*copy == 92) { /* is backslash ? */
- X *(copy + 1) = 92; /* then put another and */
- X copy += 2; /* proceed two bytes */
- X }
- X else /* else */
- X copy++; /* proceed one byte */
- X }
- X *copy = 0;
- X}
- X
- X
- Xstatic void do_expire (day, month, year)
- X int day, month, year;
- X{
- X long act_time;
- X struct tm *t;
- X time (&act_time);
- X t = localtime (&act_time);
- X month--; /* localtime uses months 0 - 11 ! */
- X if ((
- X t->tm_year > year || (t->tm_year == year && t->tm_mon > month) ||
- X (t->tm_year == year && t->tm_mon == month && t->tm_mday > day))
- X ) {
- X fprintf (stderr, "\n%s\n\n", Thas_expired[msg_type]);
- X exit (100);
- X }
- X}
- X
- X
- Xstatic void reset_l_r_s ()
- X{
- X /* Sets LINE_INFO- and REF_INFO-Arrays 'l' and 'r' into
- X their empty state.
- X */
- X int i;
- X for (i = 0; i <= r_pos; i++) { /* Alle Refinements loeschen */
- X r[i].name = NULL;
- X r[i].calls = 0;
- X }
- X s = s_root; /* Zeilenspeicher loeschen */
- X l_pos = r_pos = old_level = 0;
- X}
- X
- X
- END_OF_FILE
- if test 30121 -ne `wc -c <'crefine.c'`; then
- echo shar: \"'crefine.c'\" unpacked with wrong size!
- fi
- # end of 'crefine.c'
- fi
- echo shar: End of archive 1 \(of 4\).
- cp /dev/null ark1isdone
- MISSING=""
- for I in 1 2 3 4 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 4 archives.
- rm -f ark[1-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
-